import 'dart:async';

import 'package:ad_common/third_ad.dart';
import 'package:ad_common/third_ad_instance.dart';
import 'package:ad_common/util/log.dart';
import 'package:anythink_sdk/at_listener.dart';
import 'package:anythink_sdk/at_rewarded.dart';
import 'package:anythink_sdk/at_rewarded_response.dart';
import 'package:top_on_ad_plugin/top_on_base_ad.dart';

/// FileName top_on_ad_reward_video
/// @Author zhuqingfang
/// @Date 2022/9/26 3:00 下午
/// @Description top on ad reward video
//ad request map
Map<String, TopOnRewardVideoAd> _rewardVideoAdRequest = {};

//ad loaded map
Map<String, TopOnRewardVideoAd> _rewardVideoAdLoaded = {};

//ad show object
TopOnRewardVideoAd? _rewardVideoAdShow;

//为空初始化，不空，不初始化，确保listener只注册一次
StreamSubscription? _initRewardVideoListener;

class TopOnRewardVideoAd extends TopOnBaseAd {
  TopOnRewardVideoAd({required ThirdAdParams thirdAdParams})
      : super(thirdAdParams: thirdAdParams);

  @override
  void load() {
    //在父类执行top on sdk 初始化
    super.load();

    //可多次被调用，但只初始化一次
    _initRewardVideoListener =
        _initRewardVideoListener ?? _rewardVideoAdListener();

    //检查广告状态，如果广告正在加载中或者placementId对应的广告已经准备好，不执行加载,否则加载广告
    checkAdState(
        thirdAdType: ThirdAdType.topOnRewardVideoAd,
        placementId: thirdAdParams.placementId,
        isLoaded: (isLoaded) {
          if (isLoaded == true) {
            //如果本地有对应的placementId缓存广告或者正在请求，不再发起广告请求
            thirdAdParams.thirdAdEventCallback(
                AdCallbackEvent.loadFail,
                '${thirdAdParams.placementId} top on video ad is loading',
                {thirdAdParams.placementId: 'isLoading'});
          } else {
            //一个 placementId 对应一个实例，缓存起来，只有真正发起广告请求的时候才缓存
            _rewardVideoAdRequest[thirdAdParams.placementId] = this;

            //真正发起广告请求
            _loadRewardedVideo(placementId: thirdAdParams.placementId);
          }
        });
  }

  @override
  void show() {
    //先检查是否有可用的广告，如果有再展示
    isShowTopOnAd(
        thirdAdType: ThirdAdType.topOnRewardVideoAd,
        placementId: thirdAdParams.placementId,
        isShowAd: (isShowAd) {
          if (isShowAd == true) {
            if (_rewardVideoAdLoaded.containsKey(thirdAdParams.placementId)) {
              _rewardVideoAdShow =
                  _rewardVideoAdLoaded[thirdAdParams.placementId];
            }
            if (thirdAdParams.thirdAdExtraInputParam != null) {
              Log.i(
                  'top on show sceneId:${thirdAdParams.thirdAdExtraInputParam as String}');
            }
            //展示
            _showAd(
                placementId: thirdAdParams.placementId,
                sceneId: thirdAdParams.thirdAdExtraInputParam as String?);
          } else {
            //如果还有准备好，不展示
            Map<String, Object> infoMap = {
              thirdAdParams.placementId: 'notReady'
            };
            thirdAdParams.thirdAdEventCallback(
                AdCallbackEvent.showFail,
                '${thirdAdParams.placementId} top on video ad is notReady',
                infoMap);
          }
        });
  }
}

//获取已经加载广告的信息
_checkAdStatus({required String placementId}) {
  return ATRewardedManager.checkRewardedVideoLoadStatus(
    placementID: placementId,
  );
}

void _loadRewardedVideo({required String placementId}) {
  ATRewardedManager.loadRewardedVideo(placementID: placementId, extraMap: {
    ATRewardedManager.kATAdLoadingExtraMediaExtraKey(): '',
    ATRewardedManager.kATAdLoadingExtraUserIDKey(): '',
  });
}

//展示广告或者带场景的广告
void _showAd({required String placementId, String? sceneId}) {
  if (sceneId != null) {
    Log.i('top on enter into show scene video');
    _showSceneRewardVideoAd(placementId: placementId, sceneId: sceneId);
  } else {
    Log.i('top on enter into show no scene video');
    ATRewardedManager.showRewardedVideo(
      placementID: placementId,
    );
  }
}

//展示带场景的广告
void _showSceneRewardVideoAd(
    {required String placementId, required String sceneId}) {
  ATRewardedManager.showSceneRewardedVideo(
      placementID: placementId, sceneID: sceneId);
}

//获取所有缓存广告的信息
_getRewardedVideoValidAds({required String placementId}) {
  ATRewardedManager.getRewardedVideoValidAds(placementID: placementId).then(
      (value) =>
          Log.i('reward video ad $placementId all available ad info:$value'));
}

//注册监听广告回调
StreamSubscription _rewardVideoAdListener() {
  return ATListenerManager.rewardedVideoEventHandler.listen((value) async {
    switch (value.rewardStatus) {
      //广告加载失败
      case RewardedStatus.rewardedVideoDidFailToLoad:
        Log.i(
            "flutter rewardedVideoDidFailToLoad ---- placementID: ${value.placementID} ---- errStr:${value.requestMessage}--extra:${value.extraMap}");
        // callBack(code,)
        if (_rewardVideoAdRequest.containsKey(value.placementID)) {
          Map<String, Object> infoMap = {value.placementID: 'loadFail'};
          _rewardVideoAdRequest[value.placementID]
              ?.thirdAdParams
              .thirdAdEventCallback(
                  AdCallbackEvent.loadFail,
                  'top on reward video ad placementID :${value.placementID} load fail errStr:${value.requestMessage}',
                  infoMap);
        }
        break;
      //广告加载成功
      case RewardedStatus.rewardedVideoDidFinishLoading:
        Log.i(
            "flutter rewardedVideoDidFinishLoading ---- placementID: ${value.placementID}--extra:${value.requestMessage}");
        if (_rewardVideoAdRequest.containsKey(value.placementID)) {
          _rewardVideoAdLoaded[value.placementID] =
              _rewardVideoAdRequest[value.placementID]!;
          final adState = await _checkAdStatus(placementId: value.placementID);
          Log.i(
              'flutter rewardedVideoDidFinishLoading adInfo:${adState["adInfo"].toString()}');
          _rewardVideoAdLoaded[value.placementID]
              ?.thirdAdParams
              .thirdAdEventCallback(
                  AdCallbackEvent.loadSuccess,
                  'top on reward video ad placementID:${value.placementID}  ${value.requestMessage} video ad loaded',
                  adState['adInfo']);
        }
        //获取所有广告的缓存信息，供测试用
        _getRewardedVideoValidAds(placementId: value.placementID);
        break;
      //广告开始播放
      case RewardedStatus.rewardedVideoDidStartPlaying:
        Log.i(
            "flutter rewardedVideoDidStartPlaying ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        _rewardVideoAdShow?.thirdAdParams.thirdAdEventCallback(
            AdCallbackEvent.onShow,
            'top on reward video ad placementID:${value.placementID} video onShow',
            value.extraMap);
        break;
      //广告结束播放
      case RewardedStatus.rewardedVideoDidEndPlaying:
        Log.i(
            "flutter rewardedVideoDidEndPlaying ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      //广告播放失败
      case RewardedStatus.rewardedVideoDidFailToPlay:
        Log.i(
            "flutter rewardedVideoDidFailToPlay ---- placementID: ${value.placementID} ---- errStr:${value.extraMap}");
        _rewardVideoAdShow?.thirdAdParams.thirdAdEventCallback(
            AdCallbackEvent.showFail,
            'top on reward video ad placementID:${value.placementID} video showFail errStr:${value.extraMap}',
            value.extraMap);
        break;
      //激励成功，建议在此回调中下发奖励
      case RewardedStatus.rewardedVideoDidRewardSuccess:
        Log.i(
            "flutter rewardedVideoDidRewardSuccess ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        _rewardVideoAdShow?.thirdAdParams.thirdAdEventCallback(
            AdCallbackEvent.onReward,
            'top on reward video ad placementID:${value.placementID} video reward success',
            value.extraMap);
        break;
      //广告被点击
      case RewardedStatus.rewardedVideoDidClick:
        Log.i(
            "flutter rewardedVideoDidClick ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        _rewardVideoAdShow?.thirdAdParams.thirdAdEventCallback(
            AdCallbackEvent.onClick,
            'top on reward video ad placementID:${value.placementID} video clicked',
            value.extraMap);
        break;
      //Deeplink
      case RewardedStatus.rewardedVideoDidDeepLink:
        Log.i(
            "flutter rewardedVideoDidDeepLink ---- placementID: ${value.placementID} ---- extra:${value.extraMap} ---- isDeeplinkSuccess:${value.isDeeplinkSuccess}");
        break;
      //广告被关闭
      case RewardedStatus.rewardedVideoDidClose:
        Log.i(
            "flutter rewardedVideoDidClose ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        _rewardVideoAdShow?.thirdAdParams.thirdAdEventCallback(
            AdCallbackEvent.onClose,
            'top on reward video ad placementID:${value.placementID} video dismiss',
            value.extraMap);
        break;

      //广告开始播放（只针对穿山甲的再看一个广告）
      case RewardedStatus.rewardedVideoDidAgainStartPlaying:
        Log.i(
            "flutter rewardedVideoDidAgainStartPlaying ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      //广告结束播放（只针对穿山甲的再看一个广告）
      case RewardedStatus.rewardedVideoDidAgainEndPlaying:
        Log.i(
            "flutter rewardedVideoDidAgainEndPlaying ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      //广告播放失败（只针对穿山甲的再看一个广告）
      case RewardedStatus.rewardedVideoDidAgainFailToPlay:
        Log.i(
            "flutter rewardedVideoDidAgainFailToPlay ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      //激励成功（只针对穿山甲的再看一个广告）
      case RewardedStatus.rewardedVideoDidAgainRewardSuccess:
        Log.i(
            "flutter rewardedVideoDidAgainRewardSuccess ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      //广告被点击（只针对穿山甲的再看一个广告）
      case RewardedStatus.rewardedVideoDidAgainClick:
        Log.i(
            "flutter rewardedVideoDidAgainClick ---- placementID: ${value.placementID} ---- extra:${value.extraMap}");
        break;
      case RewardedStatus.rewardedVideoUnknown:
        Log.i("flutter rewardedVideoUnknown");
        break;
    }
  });
}
